/*
 * Created by SharpDevelop.
 * User: michaelo
 * Date: 06/10/2005
 * Time: 10:53
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
namespace Orz.LogManager 
{
	using System;
	using System.Collections;
	using Orz.LogManager.Config;
	using System.Text;
	using System.IO; 
	using System.Security.Cryptography; 
	using System.Globalization;
	
	public class PasswordHelper
	{
		private static Hashtable storedPasswords_c = new Hashtable();
		private static readonly string KEY = GenerateKey();
		
		
		
		
		public static string GetSSHPassword (logsetLogfile file_p)
		{			
			lock(PasswordHelper.storedPasswords_c)
			{
				string sHost = file_p.telnetHost.ToLower();
				string sUser = file_p.sshUsername.ToLower();
				
				string sKey = sHost + ":" + sUser;
				
				if (storedPasswords_c.ContainsKey (sKey))
				{
					return (string) storedPasswords_c[sKey];
				}
				else
				{
					
					EnterPasswordForm f = new EnterPasswordForm(sHost, sUser);
					f.ShowDialog();
					if (f.Cancelled)
					{
						return null;
					}
					else
					{
						string sPassword = f.Password;
						storedPasswords_c[sKey] = sPassword;
						return sPassword;
					}
				}
			}
		}
		
		
		
		public static void MarkDodgyPassword (logsetLogfile file_p)
		{
			string sHost = file_p.telnetHost.ToLower();
			string sUser = file_p.sshUsername.ToLower();
			
			string sKey = sHost + ":" + sUser;
			
			if (storedPasswords_c.ContainsKey (sKey))
			{
				storedPasswords_c.Remove(sKey);
			}
		}
		
		
		public static string Decrypt (string sCipherText_p)
		{
			// First we need to turn the input string into a byte array. 
	        // We presume that Base64 encoding was used 
	        byte[] vCipherBytes = Convert.FromBase64String(sCipherText_p); 
	
	        // Then, we need to turn the password into Key and IV 
	        // We are using salt to make it harder to guess our key
	        // using a dictionary attack - 
	        // trying to guess a password by enumerating all possible words. 
	        PasswordDeriveBytes pdb = new PasswordDeriveBytes(KEY, 
	            new byte[] {0x4B, 0x41, 0x4D, 0x63, 0x43, 0x61, 
	            0x75, 0x67, 0x68, 0x72, 0x61, 0x69, 0x6E}); 
	        
	        // Now get the key/IV and do the decryption using
	        // the function that accepts byte arrays. 
	        // Using PasswordDeriveBytes object we are first
	        // getting 32 bytes for the Key 
	        // (the default Rijndael key length is 256bit = 32bytes)
	        // and then 16 bytes for the IV. 
	        // IV should always be the block size, which is by
	        // default 16 bytes (128 bit) for Rijndael. 
	        // If you are using DES/TripleDES/RC2 the block size is
	        // 8 bytes and so should be the IV size. 
	        // You can also read KeySize/BlockSize properties off
	        // the algorithm to find out the sizes. 
	        byte[] vDecryptedData = Decrypt(vCipherBytes, 
	            pdb.GetBytes(32), pdb.GetBytes(16)); 
	
	        // Now we need to turn the resulting byte array into a string. 
	        // A common mistake would be to use an Encoding class for that.
	        // It does not work 
	        // because not all byte values can be represented by characters. 
	        // We are going to be using Base64 encoding that is 
	        // designed exactly for what we are trying to do. 
	        return System.Text.Encoding.Unicode.GetString(vDecryptedData); 
	    }
		
		
		
		
		
		
		
		
	    public static string Encrypt(string sClearText_p) 
	    { 
	        // First we need to turn the input string into a byte array. 
	        byte[] vClearBytes = Encoding.Unicode.GetBytes(sClearText_p); 
	
	        // Then, we need to turn the password into Key and IV 
	        // We are using salt to make it harder to guess our key
	        // using a dictionary attack - 
	        // trying to guess a password by enumerating all possible words. 
	        PasswordDeriveBytes pdb = new PasswordDeriveBytes(KEY, 
	            new byte[] {0x4B, 0x41, 0x4D, 0x63, 0x43, 0x61, 
	            0x75, 0x67, 0x68, 0x72, 0x61, 0x69, 0x6E}); 
	
	        
	        
	        // Now get the key/IV and do the encryption using the
	        // function that accepts byte arrays. 
	        // Using PasswordDeriveBytes object we are first getting
	        // 32 bytes for the Key 
	        // (the default Rijndael key length is 256bit = 32bytes)
	        // and then 16 bytes for the IV. 
	        // IV should always be the block size, which is by default
	        // 16 bytes (128 bit) for Rijndael. 
	        // If you are using DES/TripleDES/RC2 the block size is
	        // 8 bytes and so should be the IV size. 
	        // You can also read KeySize/BlockSize properties off
	        // the algorithm to find out the sizes. 
	        byte[] vEncryptedData = Encrypt(vClearBytes, 
	                 pdb.GetBytes(32), pdb.GetBytes(16)); 
	
	        // Now we need to turn the resulting byte array into a string. 
	        // A common mistake would be to use an Encoding class for that.
	        //It does not work because not all byte values can be
	        // represented by characters. 
	        // We are going to be using Base64 encoding that is designed
	        //exactly for what we are trying to do. 
	        return Convert.ToBase64String(vEncryptedData);	
	    }
	    
	    
	    
		
		private static string GenerateKey()
		{
			string s1 = "76647446344667466766746765546746";
			string s2 = "1C05F05945F01F31935C239731901F80";			
			
			byte[] b3 = new byte[s1.Length];
			
			for (int i=0; i< s1.Length; i++)
			{
				string s3 = "" + s1[i] + s2[s2.Length - (i+1)];		
				
				b3[i] = Byte.Parse(s3, NumberStyles.HexNumber);				
			}
			
			return System.Text.Encoding.ASCII.GetString(b3);			
		}
		
		
			
		
		
		
		
		
	    
	    
	    
	    
	    
	    // Encrypt a byte array into a byte array using a key and an IV 
	    private static byte[] Encrypt(byte[] vClearData_p, byte[] vKey_p, byte[] vIV_p)
	    { 
	        MemoryStream ms = new MemoryStream(); 
		  	Rijndael alg = Rijndael.Create(); 
		  	alg.Key = vKey_p; 
	        alg.IV = vIV_p; 
	  		CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); 
	  		cs.Write(vClearData_p, 0, vClearData_p.Length); 
	  		cs.Close(); 
	        byte[] vEncryptedData = ms.ToArray();
	        return vEncryptedData; 
	    } 
		
		
	    
	    
	    // Decrypt a byte array into a byte array using a key and an IV 
	    private static byte[] Decrypt(byte[] vCipherData_p, 
	                                byte[] vKey_p, byte[] vIV_p) 
	    { 
	        MemoryStream ms = new MemoryStream(); 
			Rijndael alg = Rijndael.Create(); 
			alg.Key = vKey_p; 
	        alg.IV = vIV_p; 
			CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write); 
	        cs.Write(vCipherData_p, 0, vCipherData_p.Length); 
	        cs.Close(); 
	        byte[] vDecryptedData = ms.ToArray(); 
	        return vDecryptedData; 
	    }	    
	}
}
